#ifndef _MKSQUEUE_H
#define _MKSQUEUE_H
#include <assert.h>
#include <glib.h>
#define INCLUDE_ALLOW_USERLEVEL

#define DECLARE_QUEUE_TYPE(NAME, TYPE, MAX)                                \
       typedef struct {                                                        \
                 TYPE        queue[MAX];                                              \
                 unsigned int      head;                                                    \
                 unsigned int      tail;                                                    \
                 unsigned int      count;                                                   \
                 unsigned int      capacity;                                                \
              } MKS ## NAME ## Queue;                                                 \
                                                                           \
   extern void MKS ## NAME ## Queue_Init(MKS ## NAME ## Queue *queue);            \
   extern unsigned int MKS ## NAME ## Queue_Empty(MKS ## NAME ## Queue *queue);           \
   extern unsigned int MKS ## NAME ## Queue_Full(MKS ## NAME ## Queue *queue);            \
   extern unsigned int MKS ## NAME ## Queue_Insert(MKS ## NAME ## Queue *queue, TYPE const *item); \
   extern unsigned int MKS ## NAME ## Queue_Remove(MKS ## NAME ## Queue *queue, TYPE *item);

#define DEFINE_QUEUE_FNS(NAME, TYPE, MAX)                                  \
                                                                               \
void                                                                       \
MKS ## NAME ## Queue_Init(MKS ## NAME ## Queue *queue)                     \
{                                                                          \
       queue->head = 0;                                                        \
       queue->tail = 0;                                                        \
       queue->count = 0;                                                       \
       queue->capacity = MAX;                                                  \
}                                                                          \
                                                                           \
unsigned int                                                                       \
MKS ## NAME ## Queue_Empty(MKS ## NAME ## Queue *queue)                    \
{                                                                          \
       return queue->count == 0;                                               \
}                                                                          \
                                                                           \
unsigned int                                                                       \
MKS ## NAME ## Queue_Full(MKS ## NAME ## Queue *queue)                     \
{                                                                          \
       return queue->count == queue->capacity;                                 \
}                                                                          \
                                                                           \
unsigned int                                                                       \
MKS ## NAME ## Queue_Insert(MKS ## NAME ## Queue *queue, TYPE const *item) \
{                                                                          \
       assert(queue->capacity > 0);                                            \
       if (queue->count == queue->capacity) {                                  \
                 return FALSE;                                                        \
              }                                                                       \
       queue->queue[queue->tail] = *item;                                      \
       queue->tail = (queue->tail + 1) % queue->capacity;                      \
       queue->count++;                                                         \
       return TRUE;                                                            \
}                                                                          \
                                                                           \
unsigned int                                                                       \
MKS ## NAME ## Queue_Remove(MKS ## NAME ## Queue *queue, TYPE *item)       \
{                                                                          \
       assert(queue->capacity > 0);                                            \
       if (queue->count == 0) {                                                \
                 return FALSE;                                                        \
              }                                                                       \
       *item = queue->queue[queue->head];                                      \
       queue->head = (queue->head + 1) % queue->capacity;                      \
       queue->count--;                                                         \
       return TRUE;                                                            \
}

#endif
